package animationEngine;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import utils.Globals;

/**
 * The InputFrame class represents the frame that allows the user to input the text to be
 * searched and the pattern to be searched for.
 * 
 * @author Andrei Palade
 * @author David McBrierty
 * @author Garry Sharp
 * @author Hristo Georgiev
 * @author John Dennis
 * @author Marco Sarconi
 * @version 1.0.1
 */
public class InputFrame extends javax.swing.JFrame {

	/**
	 * @serial using the default one (1L)
	 */
	private static final long serialVersionUID = 1L;		


	/** The parent of the input frame */
	private JFrame parentFrame;

	/** The size of the text input */
	private int textSize = 40;

	/** The size of the pattern input*/
	private int patternSize = 20;

	/** Stores the previous text used */
	private String previousText;

	/** Stores the previous pattern used */
	private String previousPattern;

	/** Stores the previous algorithm used */
	private String previousAlgorithm;

	private boolean done = false;


	// GUI Variables declaration - do not modify
	private javax.swing.JButton startButton;
	private javax.swing.JButton cancelButton;
	private javax.swing.JButton generateButton;
	private javax.swing.JComboBox algorithmsList;
	private javax.swing.JLabel textLabel;
	private javax.swing.JLabel patternLabel;
	private javax.swing.JLabel selectAlgLabel;
	private javax.swing.JSeparator jSeparator1;
	private javax.swing.JTextField insertTextField;
	private javax.swing.JTextField insertPatternField;
	private javax.swing.JOptionPane optionPane;
	// End of variables declaration
	float START_TIME;
	MainFrame fr;

	/** Creates new form */
	public InputFrame() {
		previousAlgorithm = null;
		previousPattern = null;
		previousText = null;
		initComponents();
		this.setVisible(true);
	}

	/** Creates new form */
	public InputFrame(String text, String pattern, String algo) {
		this.previousText = text;
		this.previousPattern = pattern;
		this.previousAlgorithm = algo;
		initComponents();
		this.setVisible(true);
	}

	/** 
	 * This method randomly generates a string from a standard lower case alphabet.
	 * 
	 * @param length - The length of the newly generated string
	 * @return The newly generated string
	 */
	public static String generateString(int length){
		char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
		StringBuilder sb = new StringBuilder();
		Random random = new Random();
		for (int i = 0; i < length; i++) {
		    char c = chars[random.nextInt(chars.length)];
		    sb.append(c);
		}
		return sb.toString();
	}
	
	/**
	 * This method generates a random pattern by calling generateString.
	 * 
	 * @param c The upper bound of the newly generated pattern size	 
	 * @return The function generateString with random generated parameter 
	 */
	public String generatePattern(int c){
		int random2 = (int) ((c-(c/5))*Math.random() + (c/5));
		return generateString(random2);
	}
	
	/**
	 * @param c The upper bound of the newly generated pattern size
	 * 
	 * @return The function generateString with random generated parameter 
	 */
	public String generateText(int a){
		int random = (int) ((a-(a/2))*Math.random() + (a/2));
		return generateString(random);
	}


	/** 
	 * This method is called from within the constructor to
	 * initialise the form.
	 */
	void initComponents() {
		
		if(previousText != null && previousPattern != null){
			insertTextField = new javax.swing.JTextField(previousText);
			insertPatternField = new javax.swing.JTextField(previousPattern);
		}
		
		else{
			insertTextField = new javax.swing.JTextField();
			insertPatternField = new javax.swing.JTextField();
		}
		
		textLabel = new javax.swing.JLabel("Scannable text");
		patternLabel = new javax.swing.JLabel("Search pattern");
		startButton = new javax.swing.JButton("Start");
		cancelButton = new javax.swing.JButton("Close");
		generateButton = new javax.swing.JButton("Generate");
		algorithmsList = new javax.swing.JComboBox();
		selectAlgLabel = new javax.swing.JLabel("Select algorithm");
		jSeparator1 = new javax.swing.JSeparator();
		optionPane = new javax.swing.JOptionPane();

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		setTitle("Start");
		setResizable(false);

		algorithmsList.setModel(new javax.swing.DefaultComboBoxModel(Globals.ALGORITHM_LIST));
		algorithmsList.setToolTipText("null");

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
								.addGroup(layout.createSequentialGroup()
										.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
												.addComponent(patternLabel) 
												.addComponent(selectAlgLabel)
												.addComponent(textLabel))
												.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
												.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
														.addComponent(insertPatternField, javax.swing.GroupLayout.PREFERRED_SIZE, 268, javax.swing.GroupLayout.PREFERRED_SIZE)
														.addGroup(layout.createSequentialGroup()
																.addComponent(algorithmsList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
																.addGap(149, 149, 149))
																.addComponent(insertTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 268, javax.swing.GroupLayout.PREFERRED_SIZE))
																.addGap(24, 24, 24))
																.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
																		.addComponent(generateButton, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
																		.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,20,122)
																		.addComponent(startButton, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE)
																		.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																		.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
																		.addContainerGap())
																		.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
																				.addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 418, Short.MAX_VALUE)
																				.addContainerGap())))
				);
		layout.setVerticalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addGap(22, 22, 22)
						.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
								.addComponent(textLabel)
								.addComponent(insertTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
								.addGap(23, 23, 23)
								.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
										.addComponent(patternLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
										.addComponent(insertPatternField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
										.addGap(18, 18, 18)
										.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(selectAlgLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(algorithmsList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
												.addGap(26, 26, 26)
												.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE)
												.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
												.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
														.addComponent(cancelButton)
														.addComponent(startButton)
														.addComponent(generateButton))
														.addGap(12, 12, 12))
				);

		optionPane.addPropertyChangeListener(new PropertyChangeListener() {

			@Override
			public void propertyChange(PropertyChangeEvent arg0) {
				optionPane.setVisible(false);

			}
		});

		/* gets the text, pattern and selected algorithm */
		startButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {


				String textFromTextField = insertTextField.getText();
				String patternFromPatternField = insertPatternField.getText();
				textFromTextField.toLowerCase();
				patternFromPatternField.toLowerCase();

				if (validateInputs(textFromTextField, patternFromPatternField)){
					
					//System.out.println("Starting main window");
					// Dispose the parent we don't need it anymore
					if(getParentFrame() != null)
						getParentFrame().dispose();			

					@SuppressWarnings("unused")
					String algo;

					if(algorithmsList.getSelectedIndex() == 0){
						algo = "naive";
					}
					else if(algorithmsList.getSelectedIndex() == 2){
						algo = "kmp";
					}
					else{
						algo = "boyer";
					}

					System.out.println("Setting done");
					done = true;
					setDone(true);

				}

			}
		});


		/* closes the frame on click */
		cancelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {

				// We want the parent back
				if(getParentFrame() != null)
					getParentFrame().setVisible(true);

				// Make the child invisible
				dispose();
				System.exit(0);
			}
		});
		
		/* generates a pattern and text */
		generateButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				insertPatternField.setText(generatePattern(10));
				insertTextField.setText(generateText(40));
			}
		});

		pack();


	}

	public void buildGUI() {

		/* Create and display the form */
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				InputFrame f = new InputFrame();

				f.setVisible(true);

			}
		});       
	}

	
	/**
	 * @description Validate all the inputs before we start the main Frame
	 *  
	 * @param textFromTextField - The text from the corresponding input field 
	 * 
	 * @param patternFromPatternField - The pattern from the corresponding input field
	 *  
	 * @return True if the inputs are valid, false otherwise
	 */
	public boolean validateInputs(String textFromTextField, String patternFromPatternField){

		// Check if one of the entries is 0
		if (textFromTextField.length() == 0){
			JOptionPane.showMessageDialog(optionPane.getParent(), "Text field is empty!");
			//optionPane.getParent().setVisible(true);
			return false;
		}
		else if (patternFromPatternField.length() == 0){			
			JOptionPane.showMessageDialog(optionPane.getParent(), "Pattern field is empty!");
			//optionPane.getParent().setVisible(true);
			return false;
		}		
		// Check if the text length is less than the pattern
		else if (textFromTextField.length() < patternFromPatternField.length()){
			JOptionPane.showMessageDialog(optionPane.getParent(), "Pattern is longer than text!");
			//if(getParent()!=null)
			//optionPane.getParent().setVisible(true);
			return false;
		}

		else if (textFromTextField.length() > getTextSize()){
			JOptionPane.showMessageDialog(optionPane.getParent(), "Text field is longer than " + getTextSize() + " characters");
			//if(getParent()!=null)
			//optionPane.getParent().setVisible(true);
			return false;
		}
		else if (patternFromPatternField.length() > getPatternSize()){
			JOptionPane.showMessageDialog(optionPane.getParent(), "Pattern field is longer than " + getPatternSize() + " characters");
			//if(getParent()!=null)
			//optionPane.getParent().setVisible(true);
			return false;
		}

		//JOptionPane.showMessageDialog(this, "Day of appointment date must be an integer.");
		if(getParent()!=null)
			optionPane.getParent().setVisible(true);
		return true;

	}

	/**
	 * @description Getter for the parent frame; 
	 * 				we want to keep him around for pocket money and stuff
	 *  
	 * @return The parent frame
	 */
	public JFrame getParentFrame() {
		return parentFrame;
	}

	/**
	 * Setter for the parent frame;
	 * 
	 * @param parentFrame 
	 */
	public void setParentFrame(JFrame parentFrame) {
		this.parentFrame = parentFrame;
	}
	
	/**
	 * 
	 * @return
	 */
	public javax.swing.JComboBox getAlgorithmsList() {
		return algorithmsList;
	}

	/**
	 * 
	 * @param algorithmsList
	 */
	public void setAlgorithmsList(javax.swing.JComboBox algorithmsList) {
		this.algorithmsList = algorithmsList;
	}
	
	/**
	 * 
	 * @return 
	 */
	public javax.swing.JTextField getInsertTextField() {
		return insertTextField;
	}

	/**
	 * 
	 * @param insertTextField
	 */
	public void setInsertTextField(javax.swing.JTextField insertTextField) {
		this.insertTextField = insertTextField;
	}

	/**
	 * 
	 * @return
	 */
	public javax.swing.JTextField getInsertPatternField() {
		return insertPatternField;
	}

	/**
	 * 
	 * @param insertPatternField
	 */
	public void setInsertPatternField(javax.swing.JTextField insertPatternField) {
		this.insertPatternField = insertPatternField;
	}

	
	/**
	 * 
	 * @return The size of the text input 
	 * */
	public int getTextSize() {
		return textSize;
	}


	/**
	 * 
	 * @param textSize 
	 * */
	public void setTextSize(int textSize) {
		this.textSize = textSize;
	}


	/**
	 * 
	 * @return The size of the pattern input
	 */

	public int getPatternSize() {
		return patternSize;
	}


	/**
	 * 
	 * @param patternSize
	 */

	public void setPatternSize(int patternSize) {
		this.patternSize = patternSize;
	}

	/**
	 * 
	 * 
	 * @return The value of the input frame state
	 */
	public boolean isDone() {
		return done;
	}

	/**
	 * 
	 * @param done Changes the value of the input frame state
	 */
	public void setDone(boolean done) {
		this.done = done;
	}

	/**
	 * 
	 * @return The previous text used
	 */
	public String getPreviousText() {
		return previousText;
	}

	/**
	 * 
	 * @param previousText The value of the previous text used
	 */
	public void setPreviousText(String previousText) {
		this.previousText = previousText;
	}

	/**
	 * 
	 * @return The value of the previous pattern used
	 */
	public String getPreviousPattern() {
		return previousPattern;
	}

	/**
	 * 
	 * @param previousPattern Sets the value of the previous pattern used
	 */
	public void setPreviousPattern(String previousPattern) {
		this.previousPattern = previousPattern;
	}

	/**
	 * 
	 * @return The name of the previous algorithm used
	 */
	public String getPreviousAlgorithm() {
		return previousAlgorithm;
	}

	/**
	 * 
	 * @param previousAlgorithm The previous algorithm used 
	 */
	public void setPreviousAlgorithm(String previousAlgorithm) {
		this.previousAlgorithm = previousAlgorithm;
	}

}
